﻿/*******************************************************************************
*	Copyright (C) 2019, Intergraph. All rights reserved.
*	File: BallValve.cs
*  	Creation Date
*	11.04.2019
*	Description: This class module is the implementation of SP3DJacketBallValve C# Symbol.
*	             This class inherits from CustomSymbolDefinition.
*  Change History:
*  dd.mmm.yyyy    who    change description
*  13.09.2023     Yuanpeng Zhang    D7数据源来自Excel(2.0.0.3)
*  27.12.2023     Yuanpeng Zhang    数据源Excel改用xml(2.0.0.4)
*  03.11.2024     Xingheng Yu       增加了D8 D9
*******************************************************************************/

using System;
using System.IO;
using System.Collections.ObjectModel;
using Ingr.SP3D.Common.Middle;
using Ingr.SP3D.Common.Middle.Services;
using Ingr.SP3D.Common.Exceptions;
using Ingr.SP3D.CommonSymbolFunctions;
using Ingr.SP3D.ReferenceData.Middle;
using System.Windows.Forms;
using Ingr.SP3D.Equipment.Middle;
using System.Reflection;
using System.Data;
using System.Xml;

namespace Ingr.SP3D.SEIDDP
{
    [CacheOption(CacheOptionType.NonCached)]
    [VariableOutputs]
    [SymbolVersion("2.0.0.3")]
    public class IMOP1 : CustomSymbolDefinition //继承后者的类
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public IMOP1() : base()
        {
            //有多少个port，就会重复进来多少次
            //这个dll就类似于pid的datasource对象           
            string DllPath = MiddleServiceProvider.SiteMgr.ActiveSite.ActivePlant.PlantCatalog.SymbolShare + @"\Custom Symbols\CommonSymbolFunctions.dll";
            if (File.Exists(DllPath) == false)
            {
                throw new Exception(@"SharedContent\Custom Symbols\CommonSymbolFunctions.dll 未找到，symbol无法工作");
            }
            else
            {
                Ingr.SP3D.Content.CommonSymbolFunctionLoader.Load();
            }
            defaultPartDataBasis = 15;
        }

        //DefinitionName/ProgID of this symbol is SEIDDP,Ingr.SP3D.SEIDDP.IMOP1
        SymbolGeometryHelper oGemHelper = new SymbolGeometryHelper();

        #region "用于接收Definition of Inputs的代码体内的变量"
        /// <summary>
        /// 来自ddp
        /// </summary>
        public double parD2, parInsulationThickness, parD4, parD3;
        /// <summary>
        /// port3 4的旋转角度
        /// </summary>
        public double parD5, parD6;
        /// <summary>
        /// 来自ddp，同时会根据xml里的数据，得到一个法兰外径时
        /// xml里是根据端口1的压力磅级（从3D数据库的下拉列表中去查询得到的）、通经算出来的
        /// </summary>
        public double parD7;
        /// <summary>
        /// port3 4带出来的引压细管的长度和宽度
        /// </summary>
        public double parD8, parD9;
        public int defaultPartDataBasis;
        public double parPortIndex4, parPortIndex3, parPortIndex2, parPortIndex1, parNpd4, parNpd3, parNpd2, parNpd1;
        public int parEndPreparation1, parScheduleThickness1, parEndStandard1, parPressureRating1, parFlowDirection1,
            parEndPreparation2, parScheduleThickness2, parEndStandard2, parPressureRating2, parFlowDirection2,
            parEndPreparation3, parScheduleThickness3, parEndStandard3, parPressureRating3, parFlowDirection3,
            parEndPreparation4, parScheduleThickness4, parEndStandard4, parPressureRating4, parFlowDirection4;
        public string parNpdUnitType1, parId1, parNpdUnitType2, parId2, parNpdUnitType3, parId3, parNpdUnitType4, parId4;
        public XmlDocument xmlDocument = new XmlDocument();
        public XmlNodeList xmlData;
        #endregion

        #region "Definition of Inputs,会从3D后台中带过来参数" 
        //这个1 2 3 4代表了唯一的序号，先后顺序。因为所有的输入参数被视为一个集合
        //名字要和bulkload表里的属性名字一致。顺序、描述其实无所谓,外部的参数会根据Name自动匹配到对应的某一个参数中。
        [InputCatalogPart(1)]
        //默认这个是1
        public InputCatalogPart m_oPartDef;
        [InputDouble(2, "FacetoFace", "D2", 0.336, true)]
        public InputDouble m_D2;
        [InputDouble(3, "Face1toCenter", "D3", 0.168)]
        public InputDouble m_D3;
        [InputDouble(4, "OrificeFlangeClearance", "D4", 0.009)]
        public InputDouble m_D4;
        [InputDouble(5, "PortRotation1", "D5", Math.PI / 180 * 30, true)]
        public InputDouble m_D5;
        [InputDouble(6, "PortRotation2", "D6", Math.PI / 180 * 315, true)]
        public InputDouble m_D6;
        [InputDouble(7, "InsulationThickness", "InsulationThickness", 0.25, true)]
        public InputDouble m_InsulationThickness;


        [InputDouble(8, "Npd", "Npd", 100, true)]
        public InputDouble m_Npd;
        [InputDouble(9, "EndPreparation", "End Preparation", 21, true)]
        public InputDouble m_EndPreparation;
        [InputDouble(10, "ScheduleThickness", "Schedule Thickness", 100, true)]
        public InputDouble m_ScheduleThickness;
        [InputDouble(11, "EndStandard", "End Standard", 5, true)]
        public InputDouble m_EndStandard;
        [InputDouble(12, "PressureRating", "Pressure Rating", 35, true)]
        public InputDouble m_PressureRating;
        [InputDouble(13, "FlowDirection", "Flow Direction", 3, true)]
        public InputDouble m_FlowDirection;
        [InputString(14, "NpdUnitType", "Npd Unit Type", "mm", true)]
        public InputString m_NpdUnitType;

        //port的话  9个一组
        [InputDouble(15, "PortIndex1", "Port Index 1", 1, true)]
        public InputDouble m_PortIndex1;
        [InputDouble(16, "Npd1", "Npd 1", 0, true)]
        public InputDouble m_Npd1;
        [InputDouble(17, "EndPreparation1", "End Preparation 1", 0, true)]
        public InputDouble m_EndPreparation1;
        [InputDouble(18, "ScheduleThickness1", "Schedule Thickness 1", 0, true)]
        public InputDouble m_ScheduleThickness1;
        [InputDouble(19, "EndStandard1", "End Standard 1", 0, true)]
        public InputDouble m_EndStandard1;
        [InputDouble(20, "PressureRating1", "Pressure Rating 1", 0, true)]
        public InputDouble m_PressureRating1;
        [InputDouble(21, "FlowDirection1", "Flow Direction 1", 0, true)]
        public InputDouble m_FlowDirection1;
        [InputString(22, "Id1", "Id 1", "VNoz1", true)]
        public InputString m_Id1;
        [InputString(23, "NpdUnitType1", "Npd Unit Type 1", "", true)]
        public InputString m_NpdUnitType1;


        [InputDouble(24, "PortIndex2", "Port Index 2", 2, true)]
        public InputDouble m_PortIndex2;
        [InputDouble(25, "Npd2", "Npd 2", 0, true)]
        public InputDouble m_Npd2;
        [InputDouble(26, "EndPreparation2", "End Preparation 2", 0, true)]
        public InputDouble m_EndPreparation2;
        [InputDouble(27, "ScheduleThickness2", "Schedule Thickness 2", 0, true)]
        public InputDouble m_ScheduleThickness2;
        [InputDouble(28, "EndStandard2", "End Standard 2", 0, true)]
        public InputDouble m_EndStandard2;
        [InputDouble(29, "PressureRating2", "Pressure Rating 2", 0, true)]
        public InputDouble m_PressureRating2;
        [InputDouble(30, "FlowDirection2", "Flow Direction 2", 0, true)]
        public InputDouble m_FlowDirection2;
        [InputString(31, "Id2", "Id 2", "VNoz2", true)]
        public InputString m_Id2;
        [InputString(32, "NpdUnitType2", "Npd Unit Type 2", "", true)]
        public InputString m_NpdUnitType2;


        [InputDouble(33, "PortIndex3", "Port Index 3", 3, true)]
        public InputDouble m_PortIndex3;
        [InputDouble(34, "Npd3", "Npd 3", 0, true)]
        public InputDouble m_Npd3;
        [InputDouble(35, "EndPreparation3", "End Preparation 3", 0, true)]
        public InputDouble m_EndPreparation3;
        [InputDouble(36, "ScheduleThickness3", "Schedule Thickness 3", 0, true)]
        public InputDouble m_ScheduleThickness3;
        [InputDouble(37, "EndStandard3", "End Standard 3", 0, true)]
        public InputDouble m_EndStandard3;
        [InputDouble(38, "PressureRating3", "Pressure Rating 3", 0, true)]
        public InputDouble m_PressureRating3;
        [InputDouble(39, "FlowDirection3", "Flow Direction 3", 0, true)]
        public InputDouble m_FlowDirection3;
        [InputString(40, "Id3", "Id 3", "VNoz3", true)]
        public InputString m_Id3;
        [InputString(41, "NpdUnitType3", "Npd Unit Type 3", "", true)]
        public InputString m_NpdUnitType3;

        [InputDouble(42, "PortIndex4", "Port Index 4", 4, true)]
        public InputDouble m_PortIndex4;
        [InputDouble(43, "Npd4", "Npd 4", 0, true)]
        public InputDouble m_Npd4;
        [InputDouble(44, "EndPreparation4", "End Preparation 4", 0, true)]
        public InputDouble m_EndPreparation4;
        [InputDouble(45, "ScheduleThickness4", "Schedule Thickness 4", 0, true)]
        public InputDouble m_ScheduleThickness4;
        [InputDouble(46, "EndStandard4", "End Standard 4", 0, true)]
        public InputDouble m_EndStandard4;
        [InputDouble(47, "PressureRating4", "Pressure Rating 4", 0, true)]
        public InputDouble m_PressureRating4;
        [InputDouble(48, "FlowDirection4", "Flow Direction 4", 0, true)]
        public InputDouble m_FlowDirection4;
        [InputString(49, "Id4", "Id 4", "VNoz4", true)]
        public InputString m_Id4;
        [InputString(50, "NpdUnitType4", "Npd Unit Type 4", "", true)]
        public InputString m_NpdUnitType4;

        public const double D7_default = 0.1;
        [InputDouble(51, "InstrumentHeight1", "D7", D7_default, true)]
        public InputDouble m_D7;
        [InputDouble(52, "InstrumentLength2", "D8", 0.1, true)]
        public InputDouble m_D8;
        [InputDouble(53, "InstrumentRadius", "D9", 0.1, true)]
        public InputDouble m_D9;
        #endregion

        #region "Definitions of Aspects and their Outputs"
        //名字要在实际outputs.add时，匹配上
        [Aspect("Physical", "Physical", AspectID.SimplePhysical)]
        [SymbolOutput("Cylinder", "主体圆柱")]
        [SymbolOutput("Flange1", "左侧法兰")]
        [SymbolOutput("Flange2", "右侧法兰")]
        [SymbolOutput("Cone1", "左侧圆台")]
        [SymbolOutput("Cone2", "右侧圆台")]
        [SymbolOutput("PNoz1", "Nozzle with out Length")]
        [SymbolOutput("PNoz2", "Nozzle with out Length")]
        [SymbolOutput("PNoz3", "Nozzle with out Length")]
        [SymbolOutput("PNoz4", "Nozzle with out Length")]
        [SymbolOutput("CylinderPort3", "CylinderPort3")]
        [SymbolOutput("CylinderPort4", "CylinderPort4")]
        [SymbolOutput("CylinderPort5", "CylinderPort5")]
        [SymbolOutput("CylinderPort6", "CylinderPort6")]
        public AspectDefinition m_Physical;  //Aspect可以理解为SymbolOutput的集合

        [Aspect("Insulation", "Insulation", AspectID.Insulation)]
        [SymbolOutput("InsulationCylinder", "Cylinder")]
        public AspectDefinition m_Insulation;

        #endregion

        #region "Construct Outputs"

        /// <summary>
        /// 造型
        /// </summary>
        protected override void ConstructOutputs()
        {
            try
            {
                parInsulationThickness = m_InsulationThickness.Value;
                parD2 = m_D2.Value;
                parD3 = m_D3.Value;
                parD4 = m_D4.Value;
                parD5 = m_D5.Value;
                parD6 = m_D6.Value;
                parD7 = m_D7.Value;
                parD8 = m_D8.Value;
                parD9 = m_D9.Value;

                // 角度会自动变为弧度进来
                // 长度会自动变为m为单位进来

                //一组port数据
                parPortIndex1 = m_PortIndex1.Value;
                parNpd1 = m_Npd1.Value;
                parEndPreparation1 = (int)m_EndPreparation1.Value;
                parScheduleThickness1 = (int)m_ScheduleThickness1.Value;
                parEndStandard1 = (int)m_EndStandard1.Value;
                parPressureRating1 = (int)m_PressureRating1.Value;
                parFlowDirection1 = (int)m_FlowDirection1.Value;
                parId1 = m_Id1.Value;
                parNpdUnitType1 = m_NpdUnitType1.Value;

                parPortIndex2 = m_PortIndex2.Value;
                parNpd2 = m_Npd2.Value;
                parEndPreparation2 = (int)m_EndPreparation2.Value;
                parScheduleThickness2 = (int)m_ScheduleThickness2.Value;
                parEndStandard2 = (int)m_EndStandard2.Value;
                parPressureRating2 = (int)m_PressureRating2.Value;
                parFlowDirection2 = (int)m_FlowDirection2.Value;
                parId2 = m_Id2.Value;
                parNpdUnitType2 = m_NpdUnitType2.Value;

                parPortIndex3 = m_PortIndex3.Value;
                parNpd3 = m_Npd3.Value;
                parEndPreparation3 = (int)m_EndPreparation3.Value;
                parScheduleThickness3 = 1; //(int)m_ScheduleThickness3.Value;
                parEndStandard3 = (int)m_EndStandard3.Value;
                parPressureRating3 = (int)m_PressureRating3.Value;
                parFlowDirection3 = (int)m_FlowDirection3.Value;
                parId3 = m_Id3.Value;
                parNpdUnitType3 = m_NpdUnitType3.Value;

                parPortIndex4 = m_PortIndex4.Value;
                parNpd4 = m_Npd4.Value;
                parEndPreparation4 = (int)m_EndPreparation4.Value;
                parScheduleThickness4 = 1;  //(int)m_ScheduleThickness4.Value;
                parEndStandard4 = (int)m_EndStandard4.Value;
                parPressureRating4 = (int)m_PressureRating4.Value;
                parFlowDirection4 = (int)m_FlowDirection4.Value;
                parId4 = m_Id4.Value;
                parNpdUnitType4 = m_NpdUnitType4.Value;

                PipeComponent DDP = (PipeComponent)m_oPartDef.Value;  //Get the part from the catalog
                SP3DConnection connection = this.OccurrenceConnection;
                //var partDataBasis = DDP.GetPropertyValue("IJDPipeComponent", "PartDataBasis");//如果要取part上的某个属性，可以这样。和spf很像

                RunPDB11002(DDP, connection, oGemHelper);


            }
            catch (Exception ex) // General Unhandled exception
            {
                throw (ex);
            }
        }

        #endregion

        #region "Geometry Construction"
        /// <summary>
        /// 最初的模板，该函数是根据不同的partDataBasis的值，来进行不同的处理
        /// </summary>
        /// <param name="DDP"></param>
        /// <param name="connection"></param>
        private void RunPDB11002(PipeComponent DDP, SP3DConnection connection, SymbolGeometryHelper oGemHelper)
        {
            Position startPoint;
            Position endPoint;
            try
            {
                if (parEndPreparation3 == 301)
                {
                    parPressureRating3 = 1;
                }
                if (parEndPreparation4 == 301)
                {
                    parPressureRating4 = 1;
                }
            }
            catch
            {

            }

            try
            {
                // UtilityFunctions.CheckParameterForZeroValues(this, "FacetoFace");

                if (UtilityFunctions.CompareDoubleLessThanOrEqualTo(parD2, 0))
                {
                    MessageBox.Show("D2不能<=0");
                    throw new Exception("D2不能<=0");
                }
                if (UtilityFunctions.CompareDoubleLessThanOrEqualTo(parD3, 0))
                {
                    MessageBox.Show("D3不能<=0");
                    throw new Exception("D3不能<=0");
                }
                if (UtilityFunctions.CompareDoubleLessThanOrEqualTo(parD4, 0))
                {
                    MessageBox.Show("D4不能<=0");
                    throw new Exception("D4不能<=0");
                }

                if (UtilityFunctions.CompareDoubleLessThanOrEqualTo(parD7, 0))
                {
                    MessageBox.Show("D7不能<=0");
                    throw new Exception("D7不能<=0");
                }
                if (parD2 < parD3)
                {
                    MessageBox.Show("D2不能小于D3");
                    throw new Exception("D2不能小于D3");
                }
                if (parD2 < parD3 + parD4)
                {
                    MessageBox.Show("D3 D4之和不能大于D2");
                    throw new Exception("D3 D4之和不能大于D2");
                }
                double BodySize;
                double NPD1, NPD3, NPD4, b, c, d, e;


                // 第 1 个port
                // DDP 或者说 动态参数的情况，都要用这种方式先创建出port，而不能用下面这个
                // PipeNozzle port2 = PortHelper.CreatePipeNozzle(pipeComponent, connection, false, 2, new Position(0, D2, 0), new Vector(-1, 0, 0), true, true);
                var port1Pos = new Position(-parD3 - parD4 / 2, 0, 0);
                PipeNozzle port1 = PortHelper.CreateDynamicPipePort(connection,
                    1, parNpd1, parNpdUnitType1, parEndPreparation1, parScheduleThickness1, parEndStandard1, parPressureRating1, parFlowDirection1, parId1,
                    defaultPartDataBasis, false, port1Pos, new Vector(-1, 0, 0), true, true);
                m_Physical.Outputs.Add("PNoz1", port1);  //Nozzle1
                UtilityFunctions.GetPipingPortData(DDP, port1, out NPD1, out b, out c, out d, out e, true);

                // 第 2 个port
                var port2Pos = new Position(parD2 - parD3 - parD4 / 2, 0, 0);
                PipeNozzle port2 = PortHelper.CreateDynamicPipePort(connection,
                    2, parNpd2, parNpdUnitType2, parEndPreparation2, parScheduleThickness2, parEndStandard2, parPressureRating2, parFlowDirection2, parId2,
                    defaultPartDataBasis, false, port2Pos, new Vector(1, 0, 0), true, true);
                m_Physical.Outputs.Add("PNoz2", port2);


                //从Excel获取D7的值
                string XmlFilePath = MiddleServiceProvider.SiteMgr.ActiveSite.ActivePlant.PlantCatalog.SymbolShare;
                if (XmlFilePath.Substring(XmlFilePath.Length - 1, 1) == "\\")
                {
                    XmlFilePath = XmlFilePath + @"Custom Symbols\孔板法兰外径尺寸表.xml";
                }
                else
                {
                    XmlFilePath = XmlFilePath + @"\Custom Symbols\孔板法兰外径尺寸表.xml";
                }

                if (ReadXmlFile(XmlFilePath, ref xmlDocument, ref xmlData))
                {
                    try
                    {
                        MetadataManager oMetaMgr = MiddleServiceProvider.SiteMgr.ActiveSite.ActivePlant.PlantModel.MetadataMgr;
                        CodelistInformation oCodelistInformation = oMetaMgr.GetCodelistInfo("PressureRating", "REFDAT");
                        CodelistItem oCodelistItem = oCodelistInformation.GetCodelistItem(port1.PressureRating);
                        bool NotFinedit = true;
                        foreach (XmlNode oxmlNode in xmlData)
                        {
                            if (oxmlNode.Attributes["PressureRating"].Value == oCodelistItem.DisplayName && oxmlNode.Attributes["Npd1_DN"].Value == "DN" + port1.NPD.Size.ToString())
                            {
                                parD7 = double.Parse(oxmlNode.Attributes["FlangeOutsideDiameter"].Value) * 0.001;
                                NotFinedit = false;
                                break;
                            }
                        }
                        if (NotFinedit)
                        {
                            MessageBox.Show(@"\\SharedContent\Custom Symbols\孔板法兰外径尺寸表.xml中未定义该PressureRating和Npd下的法兰外径，请手动修改InstrumentHeight1。");
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                }
                else
                {
                    MessageBox.Show(@"\\SharedContent\Custom Symbols\孔板法兰外径尺寸表.xml 未找到，D7数据需要输入。");
                    throw new Exception(@"\\SharedContent\Custom Symbols\孔板法兰外径尺寸表.xml 未找到，D7数据需要输入。");
                }


                if (parD7 == D7_default) //如果是默认值
                {
                    parD7 = 2 * NPD1;
                }

                if (NPD1 > parD7 * 0.5)
                {
                    BodySize = parD7 * 0.5;
                }
                else
                {
                    BodySize = NPD1;
                }


                double flgthk1 = 0.2 * parD2;
                //d3
                //d2-d3
                if (parD3 < 0.5 * parD2) //防止突出
                {
                    if (flgthk1 * 2 > parD3)
                    {
                        flgthk1 = parD3 * 0.8 / 2;
                    }
                }
                else
                {
                    if (flgthk1 * 2 > parD2 - parD3)
                    {
                        flgthk1 = (parD2 - parD3) * 0.8 / 2;
                    }
                }

                // 第 3 个port
                PipeNozzle port3 = PortHelper.CreateDynamicPipePort(connection,
                    3, parNpd3, parNpdUnitType3, parEndPreparation3, parScheduleThickness3, parEndStandard3, parPressureRating3, parFlowDirection3, parId3,
                    defaultPartDataBasis, false, new Position(-flgthk1 / 2 - parD4 / 2, (parD8 + parD7 / 2) * Math.Sin(parD5), (parD8 + parD7 / 2) * Math.Cos(parD5)), new Vector(0, Math.Sin(parD5), Math.Cos(parD5)), true, true);
                m_Physical.Outputs.Add("PNoz3", port3);
                //上述创建Port后，可以拿到port具体的一些值
                UtilityFunctions.GetPipingPortData(DDP, port3, out NPD3, out b, out c, out d, out e, true);

                // port3上的支管 
                startPoint = new Position(-flgthk1 / 2 - parD4 / 2, parD7 / 2 * Math.Sin(parD5), parD7 / 2 * Math.Cos(parD5));
                endPoint = new Position(-flgthk1 / 2 - parD4 / 2, (parD8 + parD7 / 2) * Math.Sin(parD5), (parD8 + parD7 / 2) * Math.Cos(parD5));
                var body = Graphics3D.CreateCylinder(startPoint, endPoint, NPD3, true);
                m_Physical.Outputs.Add("CylinderPort3", body);

                // port3上的支管上，代表可能有的操作元件 
                startPoint = new Position(-flgthk1 / 2 - parD4 / 2, (parD8 * 0.7 + parD7 / 2) * Math.Sin(parD5), (parD8 * 0.7 + parD7 / 2) * Math.Cos(parD5));
                endPoint = new Position(-flgthk1 / 2 - parD4 / 2, (parD8 + parD7 / 2) * Math.Sin(parD5), (parD8 + parD7 / 2) * Math.Cos(parD5));
                body = Graphics3D.CreateCylinder(startPoint, endPoint, parD9, true);
                m_Physical.Outputs.Add("CylinderPort5", body);

                // 第 4 个port
                PipeNozzle port4 = PortHelper.CreateDynamicPipePort(connection,
                    4, parNpd4, parNpdUnitType4, parEndPreparation4, parScheduleThickness4, parEndStandard4, parPressureRating4, parFlowDirection4, parId4,
                    defaultPartDataBasis, false, new Position(flgthk1 / 2 + parD4 / 2, (parD8 + parD7 / 2) * Math.Sin(parD6), (parD8 + parD7 / 2) * Math.Cos(parD6)), new Vector(0, Math.Sin(parD6), Math.Cos(parD6)), true, true);
                m_Physical.Outputs.Add("PNoz4", port4);
                UtilityFunctions.GetPipingPortData(DDP, port4, out NPD4, out b, out c, out d, out e, true);
                // port4上的支管 
                startPoint = new Position(flgthk1 / 2 + parD4 / 2, parD7 / 2 * Math.Sin(parD6), parD7 / 2 * Math.Cos(parD6));
                endPoint = new Position(flgthk1 / 2 + parD4 / 2, (parD8 + parD7 / 2) * Math.Sin(parD6), (parD8 + parD7 / 2) * Math.Cos(parD6));
                body = Graphics3D.CreateCylinder(startPoint, endPoint, NPD4, true);
                m_Physical.Outputs.Add("CylinderPort4", body);

                // port4上的支管上，代表可能有的操作元件 
                startPoint = new Position(flgthk1 / 2 + parD4 / 2, (parD8 * 0.7 + parD7 / 2) * Math.Sin(parD6), (parD8 * 0.7 + parD7 / 2) * Math.Cos(parD6));
                endPoint = new Position(flgthk1 / 2 + parD4 / 2, (parD8 + parD7 / 2) * Math.Sin(parD6), (parD8 + parD7 / 2) * Math.Cos(parD6));
                body = Graphics3D.CreateCylinder(startPoint, endPoint, parD9, true);
                m_Physical.Outputs.Add("CylinderPort6", body);

                MiddleServiceProvider.ErrorLogger.Log($"&&&SEI DDP IMOP1&&&,{Assembly.GetExecutingAssembly().GetName().Version.ToString()}", 0);
                //if (parNpdUnitType3.ToUpper() == "IN")  //没必要了，因为GetPipingPortData可以直接拿到转换为m为单位的具体数值
                //{
                //    if (BodySize * 1000 > parNpd3 * 25.4)
                //    {
                //        BodySize = parNpd3 * 25.4 / 1000;
                //    }
                //}
                //else if (parNpdUnitType3.ToUpper() == "MM")
                //{
                //    if (BodySize * 1000 > parNpd3)
                //    {
                //        BodySize = parNpd3 / 1000;
                //    }
                //}

                // 第 1 个 圆柱 
                //Insert Code for Output1(Body)
                startPoint = port1Pos;
                endPoint = port2Pos;
                body = Graphics3D.CreateCylinder(startPoint, endPoint, BodySize, true);
                m_Physical.Outputs.Add("Cylinder", body);

                // 第 1 个 保温 
                body = Graphics3D.CreateCylinder(startPoint, endPoint, BodySize + 2 * parInsulationThickness, true);
                m_Insulation.Outputs.Add("InsulationCylinder", body);

                // 第 4 个 法兰圆柱
                startPoint = new Position(-parD4 / 2, 0, 0);
                endPoint = new Position(-parD4 / 2 - flgthk1, 0, 0);
                body = Graphics3D.CreateCylinder(startPoint, endPoint, parD7, true);
                m_Physical.Outputs.Add("Flange1", body);

                // 第 5 个 法兰圆柱
                startPoint = new Position(parD4 / 2, 0, 0);
                endPoint = new Position(parD4 / 2 + flgthk1, 0, 0);
                body = Graphics3D.CreateCylinder(startPoint, endPoint, parD7, true);
                m_Physical.Outputs.Add("Flange2", body);

                // 第 2 个 圆台
                Position centerBase = new Position(-parD4 / 2 - flgthk1, 0, 0);  //大头
                Position centerTop = new Position(-parD4 / 2 - flgthk1 * 2, 0, 0);  //小头
                var body2 = Graphics3D.CreateCone(centerBase, centerTop, parD7 * 0.9 / 2, 0.6 * parD7 / 2, true);
                m_Physical.Outputs.Add("Cone1", body2);

                // 第 3 个 圆台
                centerBase = new Position(parD4 / 2 + flgthk1, 0, 0);  //大头
                centerTop = new Position(parD4 / 2 + flgthk1 * 2, 0, 0);  //小头
                body2 = Graphics3D.CreateCone(centerBase, centerTop, parD7 * 0.9 / 2, 0.6 * parD7 / 2, true);
                m_Physical.Outputs.Add("Cone2", body2);





            }
            catch (Exception ex) // General Unhandled exception
            {
                throw ex;
            }
        }
        #endregion
        public static bool ReadXmlFile(string XmlFileName, ref XmlDocument xmlDatas, ref XmlNodeList xmlData)
        {

            bool result = false;
            try
            {
                FileInfo fileInfo = new FileInfo(XmlFileName);
                if (fileInfo.Length != 0L)
                {
                    xmlDatas.Load(XmlFileName);
                    XmlNodeList elementsByTagName = xmlDatas.GetElementsByTagName("Datas");
                    if (elementsByTagName.Count == 1)
                    {
                        xmlData = xmlDatas.GetElementsByTagName("Data");
                        result = true;
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return result;
        }



    }

}

